package com.zs.games.utils;


import com.zs.games.resultTool.ResultCodeEnum;
import com.zs.games.entity.UserInfo;
import com.zs.games.exception.APIException;
import com.zs.games.vo.LoginUserVo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;

/**
 * JWT工具类
 */
@Slf4j
public class JwtTokenUtils implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 密钥
     */
    private static String SECRET = "games";
    private static final String ISSUER = "AAA";

    private  static final long EXPIRE_TIME = 24 * 3600 * 1000 * 20;


    private static final String ROLE_ID = "roleId";
    private static final String USER_ID = "userId";
    private static final String USER_NAME = "userName";
    private static final String NICK_NAME = "nickName";


    /**
     * 生成token
     *
     * @return token
     */
    public static String createToken(UserInfo userInfo) {
        HashMap<String, Object> claims = new HashMap<>();
        claims.put(USER_ID, userInfo.getUserId());
        claims.put(USER_NAME, userInfo.getUserName());
        claims.put(ROLE_ID, userInfo.getRoleId());
        claims.put(NICK_NAME, userInfo.getNickName());
        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                //设置用户信息
                .setClaims(claims)
                //设置发证人
                .setIssuer(ISSUER)
                .setSubject(userInfo.getUserId().toString())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))
                .compact();
        return token;
    }

    /**
     * 从令牌中获取用户Id
     *
     * @param token 令牌
     * @return 用户名
     */
    private  Long getUserIdFromToken(String token) {
        Long userId;
        try {
            Claims claims = getClaimsFromToken(token);
            userId = Long.valueOf(claims.getSubject());
        } catch (Exception e) {
            userId = null;
        }
        return userId;
    }


    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    public static Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new APIException(ResultCodeEnum.TOKEN_ERR);
        }
        return claims;
    }
    /**
     * 
     * 获取登录信息，验证token后的
     * @Author: wm
     */
    public static LoginUserVo getUserInfoA(){
        LoginUserVo userInfo = getUserInfo();
        if (userInfo == null){
            throw new APIException(ResultCodeEnum.TOKEN_ERR);
        }
        return userInfo;
    }
    /**
     * 获取登录信息
     */
    public static LoginUserVo getUserInfo(){
        String token = getToken();
        if (StringUtils.isBlank(token)){
            return null;
        }
        Claims claims;
        LoginUserVo loginUserVo = new LoginUserVo();
        try {
            claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
            String ids = claims.getSubject();
            Integer id = Integer.parseInt(ids);
            loginUserVo.setUserId(id);
            loginUserVo.setUserName(String.valueOf(claims.get(USER_NAME)));
            loginUserVo.setNickName(String.valueOf(claims.get(NICK_NAME)));

        } catch (Exception e) {
            throw new APIException(ResultCodeEnum.TOKEN_ERR);
        }
        return loginUserVo;
    }
    /**
     *
     * 获取token
     * @Author: wm
     */
    private static String getToken() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            return request.getHeader("token");
        }
        return null;
    }

    /**
     * 判断令牌是否过期
     *
     * @param token 令牌
     * @return 是否过期
     */
    public static Boolean isTokenExpired(String token) {
        try {

            Claims claims = getClaimsFromToken(token);
            if (claims == null){
                log.error("token已经过期或错误");
                return true;
            }
            Date expiration = claims.getExpiration();
            return expiration.before(new Date());
        } catch (Exception e) {
            log.error("token解析异常：", token, e);
            //e.printStackTrace();
            return true;
        }
    }



}